home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 1 Issue 2 / PDCD-1 - Issue 02.iso / _utilities / utilities / 003 / _gs / !GS / c / IUTIL < prev    next >
Text File  |  1991-10-26  |  10KB  |  370 lines

  1. /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* iutil.c */
  21. /* Utilities for Ghostscript interpreter */
  22. #include "memory_.h"
  23. #include "string_.h"
  24. #include "ghost.h"
  25. #include "errors.h"
  26. #include "alloc.h"
  27. #include "iutil.h"            /* for checking prototypes */
  28. #include "name.h"
  29. #include "ostack.h"            /* for opdef.h */
  30. #include "opdef.h"            /* for obj_cvs */
  31. #include "store.h"
  32. #include "gsmatrix.h"
  33. #include "gxdevice.h"            /* for gx_color_index */
  34. #include "gzcolor.h"
  35.  
  36. /* ------ Object utilities ------ */
  37.  
  38. /* Copy refs from one place to another. */
  39. void
  40. refcpy_to_old(register ref *to, register ref *from, register uint size,
  41.   char *cname)
  42. {    while ( size-- ) ref_assign_old(to, from, cname), to++, from++;
  43. }
  44. void
  45. refcpy_to_new(register ref *to, register ref *from, register uint size)
  46. {    while ( size-- ) ref_assign_new(to, from), to++, from++;
  47. }
  48.  
  49. /* Fill a new object with nulls. */
  50. void
  51. refset_null(register ref *to, register uint size)
  52. {    while ( size-- ) make_null_new(to), to++;
  53. }
  54.  
  55. /* Compare two objects for equality.  Return 1 if equal, 0 if not. */
  56. int
  57. obj_eq(register ref *pref1, register ref *pref2)
  58. {    ref nref;
  59.     if ( r_btype(pref1) != r_btype(pref2) )
  60.        {    /* Only a few cases need be considered here: */
  61.         /* integer/real, name/string, and vice versa. */
  62.         switch ( r_type(pref1) )
  63.            {
  64.         case t_integer:
  65.             return (r_type(pref2) == t_real &&
  66.                 pref2->value.realval == pref1->value.intval);
  67.         case t_real:
  68.             return (r_type(pref2) == t_integer &&
  69.                 pref2->value.intval == pref1->value.realval);
  70.         case t_name:
  71.             if ( r_type(pref2) != t_string ) return 0;
  72.             name_string_ref(pref1, &nref);
  73.             pref1 = &nref;
  74.             break;
  75.         case t_string:
  76.             if ( r_type(pref2) != t_name ) return 0;
  77.             name_string_ref(pref2, &nref);
  78.             pref2 = &nref;
  79.             break;
  80.         default:
  81.             return 0;
  82.            }
  83.        }
  84.     /* Now do a type-dependent comparison. */
  85.     /* This would be very simple if we always filled in */
  86.     /* all 8 bytes of a ref, but we currently don't. */
  87.     switch ( r_btype(pref1) )
  88.        {
  89.     case t_array:
  90.         return (pref1->value.refs == pref2->value.refs &&
  91.             r_size(pref1) == r_size(pref2));
  92.     case t_mixedarray:
  93.     case t_shortarray:
  94.         return (pref1->value.packed == pref2->value.packed &&
  95.             r_size(pref1) == r_size(pref2));
  96.     case t_boolean:
  97.         return (pref1->value.index == pref2->value.index);
  98.     case t_dictionary:
  99.         return (pref1->value.pdict == pref2->value.pdict);
  100.     case t_file:
  101.         return (pref1->value.pfile == pref2->value.pfile);
  102.     case t_fontID:
  103.         return (pref1->value.pfont == pref2->value.pfont);
  104.     case t_integer:
  105.         return (pref1->value.intval == pref2->value.intval);
  106.     case t_mark:
  107.     case t_null:
  108.         return 1;
  109.     case t_name:
  110.         return (pref1->value.pname == pref2->value.pname);
  111.     case t_oparray:
  112.     case t_operator:
  113.         return (op_index(pref1) == op_index(pref2));
  114.     case t_real:
  115.         return (pref1->value.realval == pref2->value.realval);
  116.     case t_save:
  117.         return (pref1->value.psave == pref2->value.psave);
  118.     case t_string:
  119.         return (!bytes_compare(pref1->value.bytes, r_size(pref1),
  120.                        pref2->value.bytes, r_size(pref2)));
  121.     case t_color:
  122.        {    struct gs_color_s
  123.           *pc1 = pref1->value.pcolor,
  124.           *pc2 = pref2->value.pcolor;
  125.         return
  126.           ( pc1->red == pc2->red && pc1->green == pc2->green &&
  127.             pc1->blue == pc2->blue && pc1->not_black == pc2->not_black
  128.           );
  129.        }
  130.     case t_device:
  131.         return (pref1->value.pdevice == pref2->value.pdevice);
  132.        }
  133.     return 0;            /* shouldn't happen! */
  134. }
  135.  
  136. /* Create a printable representation of an object, a la cvs. */
  137. /* Return 0 if OK, <0 if the destination wasn't large enough. */
  138. int
  139. obj_cvs(ref *op, byte *str, uint len, uint *prlen)
  140. {    char buf[30];            /* big enough for any float */
  141.     byte *pstr = (byte *)buf;
  142.     uint plen;
  143.     ref nref;
  144.     switch ( r_btype(op) )
  145.        {
  146.     case t_boolean:
  147.         pstr = (byte *)(op->value.index ? "true" : "false");
  148.         break;
  149.     case t_integer:
  150.         sprintf(buf, "%ld", op->value.intval);
  151.         break;
  152.     case t_name:
  153.         name_string_ref(op, &nref);    /* name string */
  154. cvname:        pstr = nref.value.bytes;
  155.         plen = r_size(&nref);
  156.         goto nl;
  157.     case t_oparray:
  158.         name_index_ref(op_array_nx_table[op_index(op) - op_def_count], &nref);
  159.         name_string_ref(&nref, &nref);
  160.         goto cvname;
  161.     case t_operator:
  162.        {    /* Recover the name from the initialization table. */
  163.         uint index = op_index(op);
  164.         if ( index != 0 )
  165.            {    pstr = (byte *)(op_def_table[index]->oname + 1);
  166.             break;
  167.            }
  168.        }
  169.         /* Internal operator, no name. */
  170.         sprintf(buf, "operator_%lx", (ulong)op->value.opproc);
  171.         break;
  172.     case t_real:
  173.         sprintf(buf, "%g", op->value.realval);
  174.         break;
  175.     case t_string:
  176.         pstr = op->value.bytes;
  177.         plen = r_size(op);
  178.         goto nl;
  179.     default:
  180.         pstr = (byte *)"--nostringval--";
  181.        }
  182.     plen = strlen((char *)pstr);
  183. nl:    if ( plen > len ) return e_rangecheck;
  184.     memcpy(str, pstr, plen);
  185.     *prlen = plen;
  186.     return 0;
  187. }
  188.  
  189. /* ------ String utilities ------ */
  190.  
  191. /* Compare two strings, returning -1 if the first is less, */
  192. /* 0 if they are equal, and 1 if first is greater. */
  193. /* We can't use memcmp, because we always use unsigned characters. */
  194. int
  195. bytes_compare(byte *s1, uint len1, byte *s2, uint len2)
  196. {    register uint len = len1;
  197.     if ( len2 < len ) len = len2;
  198.        {    register byte *p1 = s1;
  199.         register byte *p2 = s2;
  200.         while ( len-- )
  201.             if ( *p1++ != *p2++ )
  202.                 return (p1[-1] < p2[-1] ? -1 : 1);
  203.        }
  204.     /* Now check for differing lengths */
  205.     return (len1 == len2 ? 0 : len1 < len2 ? -1 : 1);
  206. }
  207.  
  208. /* Test whether a string matches a pattern with wildcards. */
  209. /* '*' = any substring, '?' = any character, '\' quotes next character. */
  210. int
  211. string_match(byte *str, uint len, byte *pstr, uint plen)
  212. {    byte *pback = 0;
  213.     byte *p = pstr, *pend = pstr + plen;
  214.     byte *sp = str, *spend = str + len;
  215.     uint matched = 0;
  216.     while ( p < pend )
  217.        {    byte ch = *p;
  218.         switch ( ch )
  219.            {
  220.         case '*':
  221.             pback = ++p, matched = 0;
  222.             continue;
  223.         case '?':
  224.             if ( sp == spend ) return 0;    /* str too short */
  225.             p++, sp++, matched++;
  226.             continue;
  227.         case '\\':
  228.             if ( ++p == pend ) return 1;    /* bad pattern */
  229.             ch = *p;
  230.            }
  231.         if ( sp == spend ) return 0;    /* str too short */
  232.         if ( *sp == ch )
  233.             p++, sp++, matched++;
  234.         else if ( pback == 0 )
  235.             return 0;    /* no * to back up to */
  236.         else
  237.            {    sp += 1 - matched;
  238.             p = pback;
  239.             matched = 0;
  240.            }
  241.        }
  242.     return 1;
  243. }
  244.  
  245. /* Compute a hash for a string */
  246. uint
  247. string_hash(byte *ptr, uint len)
  248. {    register byte *p = ptr;
  249.     register uint hash = 0;
  250.     register uint n = len;
  251.     while ( n-- ) hash = hash * 19 + *p++;
  252.     return hash;
  253. }
  254.  
  255. /* Convert a C string to a Ghostscript string */
  256. int
  257. string_to_ref(char *cstr, ref *pref, char *cname)
  258. {    uint size = strlen(cstr);
  259.     char *str = alloc(size, 1, cname);
  260.     if ( str == 0 ) return e_VMerror;
  261.     memcpy(str, cstr, size);
  262.     make_tasv(pref, t_string, a_all, size, bytes, (byte *)str);
  263.     return 0;
  264. }
  265.  
  266. /* Convert a Ghostscript string to a C string. */
  267. /* Return 0 iff the buffer can't be allocated. */
  268. char *
  269. ref_to_string(ref *pref, char *client_name)
  270. {    uint size = r_size(pref);
  271.     char *str = alloc(size + 1, 1, client_name);
  272.     if ( str == 0 ) return 0;
  273.     memcpy(str, (char *)pref->value.bytes, size);
  274.     str[size] = 0;
  275.     return str;
  276. }
  277.  
  278. /* ------ Operand utilities ------ */
  279.  
  280. /* Get N numeric operands from the stack. */
  281. /* Return a bit-mask indicating which ones are integers, */
  282. /* or a (negative) error indication. */
  283. /* The 1-bit in the bit-mask refers to the bottommost stack entry. */
  284. /* Store float versions of the operands at pval. */
  285. int
  286. num_params(ref *op, int count, float *pval)
  287. {    int mask = 0;
  288.     pval += count;
  289.     while ( --count >= 0 )
  290.        {    mask <<= 1;
  291.         switch ( r_type(op) )
  292.            {
  293.         case t_real:
  294.             *--pval = op->value.realval;
  295.             break;
  296.         case t_integer:
  297.             *--pval = op->value.intval;
  298.             mask++;
  299.             break;
  300.         default:
  301.             return e_typecheck;
  302.            }
  303.         op--;
  304.        }
  305.     return mask;
  306. }
  307.  
  308. /* Get a real parameter. */
  309. /* If an error is returned, the return value is not updated. */
  310. int
  311. real_param(ref *op, float *pparam)
  312. {    switch ( r_type(op) )
  313.        {
  314.     case t_integer: *pparam = op->value.intval; break;
  315.     case t_real: *pparam = op->value.realval; break;
  316.     default: return e_typecheck;
  317.        }
  318.     return 0;
  319. }
  320.  
  321. /* ------ Matrix utilities ------ */
  322.  
  323. /* Check for a matrix operand with read access. */
  324. /* Return 0 if OK, error code if not. */
  325. /* Store an all-float version of the matrix in *pmat. */
  326. int
  327. read_matrix(ref *op, gs_matrix *pmat)
  328. {    switch ( r_type(op) )
  329.        {
  330.     default: return e_typecheck;
  331.     case t_array: ;
  332.        }
  333.     if ( r_size(op) != 6 ) return e_rangecheck;
  334.     if ( !r_has_attrs(op, a_read) ) return e_invalidaccess;
  335.     *pmat = *(gs_matrix *)op->value.refs;
  336.        {    ref *pel = (ref *)pmat;
  337.         int i;
  338.         for ( i = 0; i < 6; i++ )
  339.            {    switch ( r_type(pel) )
  340.                {
  341.             default: return e_typecheck;
  342.             case t_integer:
  343.                 make_real(pel, pel->value.intval);
  344.             case t_real: ;
  345.                }
  346.             pel++;
  347.            }
  348.        }
  349.     return 0;
  350. }
  351.  
  352. /* Check for a matrix operand with write access. */
  353. /* Return 0 if OK, error code if not. */
  354. /* Initialize the matrix to an identity matrix */
  355. /* (to set the types and attributes properly.) */
  356. int
  357. write_matrix(register ref *op)
  358. {    ref *aptr;
  359.     int i;
  360.     if ( !r_has_type(op, t_array) ) return e_typecheck;
  361.     if ( !r_has_attrs(op, a_write) ) return e_invalidaccess;
  362.     if ( r_size(op) != 6 ) return e_rangecheck;
  363.     aptr = op->value.refs;
  364.     for ( i = 5; i >= 0; i--, aptr++ )
  365.       { ref_save(aptr, "write_matrix");    /* we're going to overwrite */
  366.       }
  367.     gs_make_identity((gs_matrix *)op->value.refs);
  368.     return 0;
  369. }
  370.